﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using DES;
using Xxtea;
using MD5;
using System.Windows.Forms;

namespace DecJson
{
    class Program
    {
        static string licenceIOS = "";
        static string licenceAndroid = "";
        static void Main(string[] args)
        {
            if (args.Length != 1 || !File.Exists(args[0]))
            {
                Console.WriteLine("DecJson test.json or DecJson test.dll or DecJson test.ab");
                return;
            }
            string path = args[0];
            if (path.EndsWith(".json"))
            {
                string data = File.ReadAllText(path);
                if (data[0] != '{')
                {
                    string dataOut = DESEncryption.Decrypt(data, "com.DiMo");
                    File.WriteAllText(path, dataOut);
                }
                else
                {
                    string dataOut = DESEncryption.Encrypt(data, "com.DiMo");
                    File.WriteAllText(path, dataOut);
                }
            }
            else if (path.EndsWith(".dll"))
            {
                byte[] data = File.ReadAllBytes(path);
                if (data[0] != 'M')
                {
                    byte[] dataOut = XXTEA.Decrypt(data, "d.6SGE2.@");
                    File.WriteAllBytes(path, dataOut);
                }
                else
                {
                    byte[] dataOut = XXTEA.Encrypt(data, "d.6SGE2.@");
                    File.WriteAllBytes(path, dataOut);
                }
            }
            else
            {
                string fullName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
                string pathName = Path.GetDirectoryName(fullName);
                string dllFile = pathName + "\\Assembly-CSharp.dll";
                string metadata = pathName + "\\global-metadata.dat";
                if (!File.Exists(dllFile) && !File.Exists(metadata))
                {
                    MessageBox.Show("需要从安装包里拷贝一个Assembly-CSharp.dll (安卓)\r\n或者global-metadata.dat (IOS)\r\n放到解密工具所在目录！！！\r\n就可以解密这个安装包里的资源！！！");
                    return;
                }
                if (File.Exists(dllFile))
                {
                    if (!GetAndroidLicense(dllFile))
                    {
                        MessageBox.Show("解密工具所在目录的Assembly-CSharp.dll内容不对！！！");
                        return;
                    }
                }
                if (File.Exists(metadata))
                {
                    if (!GetIOSLicense(metadata))
                    {
                        MessageBox.Show("解密工具所在目录的global-metadata.dat内容不对！！！");
                        return;
                    }
                }
                if (string.IsNullOrEmpty(licenceIOS) && string.IsNullOrEmpty(licenceAndroid))
                {
                    MessageBox.Show("需要拷贝一个Assembly-CSharp.dll或者global-metadata.dat放到解密工具所在目录！！！");
                    return;
                }
                string licence = licenceAndroid;
                if (!string.IsNullOrEmpty(licenceIOS))
                {
                    licence = licenceIOS;
                }
                byte[] data = File.ReadAllBytes(path);
                if (data[0] == 'U')
                {
                    File.WriteAllBytes(path, XXTEA.Encrypt(data, MD5Util.GetMD5Hash(licence)));
                }
                else
                {
                    File.WriteAllBytes(path, XXTEA.Decrypt(data, MD5Util.GetMD5Hash(licence)));
                }
            }
        }
        public static string GetLicense()
        {
            return Encoding.UTF8.GetString(Convert.FromBase64String("eyJTZXJ2ZXJIb3N0IjoibG9nby5kajAyNy5jb20iLCJTZXJ2ZXJQb3J0Ijo4MzAwLCJWZXJzaW9uIjoiMy40LjEuMCIsIkZyYW1lUmF0ZSI6NjAsIkVuYWJsZUVuY3J5cHRpb24iOnRydWUsIkVuYWJsZVZlcmlmeUFCIjp0cnVlLCJFbmFibGVDYWNoZUFCIjp0cnVlLCJBdXRvQ2xlYW5DYWNoZSI6dHJ1ZSwiRW5hYmxlQnVnbHkiOnRydWUsIkJ1Z2x5QXBwSUQiOiI5MDAwMDkzMjIiLCJGaXhlZFdpZHRoIjozNjMsIkZpeGVkSGVpZ2h0Ijo0MjgsIkZpeGVkU2l6ZSI6ZmFsc2UsIlVzZUxhdW5jaGVyIjpmYWxzZSwiRm9yY2VTaW5nbGV0b24iOnRydWUsIkVuYWJsZUxvZzJGaWxlIjp0cnVlLCJMb2dMZXZlbCI6MCwiQ3VzdG9tRGF0YSI6bnVsbH0="));
        }
        public static bool GetAndroidLicense(string path)
        {
            byte[] data = File.ReadAllBytes(path);
            if (data[0] != 'M')
            {
                data = XXTEA.Decrypt(data, "d.6SGE2.@");
            }
            int posStart = IndexOf(data, Encoding.Unicode.GetBytes("eyJTZXJ2ZXJ"));
            if (posStart == -1)
            {
                return false;
            }
            byte[] endMark = new byte[2]; 
            endMark[0] = 0x00;
            endMark[1] = 0x00;
            int posEnd = IndexOf(data, endMark, posStart);
            if (posEnd == -1)
            {
                return false;
            }
            posEnd++;
            int len = posEnd - posStart;
            byte[] licData = new byte[len];
            Array.Copy(data, posStart, licData, 0, len);
            licenceAndroid = Encoding.Unicode.GetString(licData);
            licenceAndroid = Encoding.UTF8.GetString(Convert.FromBase64String(licenceAndroid));
            return true;
        }
        public static bool GetIOSLicense(string path)
        {
            byte[] data = File.ReadAllBytes(path);
            int posStart = IndexOf(data, Encoding.UTF8.GetBytes("eyJTZXJ2ZXJ"));
            if (posStart == -1)
            {
                return false;
            }
            int posEnd = IndexOf(data, Encoding.UTF8.GetBytes("yyyyMMddhhmmssID"), posStart);
            if (posEnd == -1)
            {
                return false;
            }
            posEnd-=32;
            int len = posEnd - posStart;
            byte[] licData = new byte[len];
            Array.Copy(data, posStart, licData, 0, len);
            licenceIOS = Encoding.UTF8.GetString(licData);
            licenceIOS = Encoding.UTF8.GetString(Convert.FromBase64String(licenceIOS));
            return true;
        }
        /// <summary>
        /// 报告指定的 System.Byte[] 在此实例中的第一个匹配项的索引。
        /// </summary>
        /// <param name="srcBytes">被执行查找的 System.Byte[]。</param>
        /// <param name="searchBytes">要查找的 System.Byte[]。</param>
        /// <returns>如果找到该字节数组，则为 searchBytes 的索引位置；如果未找到该字节数组，则为 -1。如果 searchBytes 为 null 或者长度为0，则返回值为 -1。</returns>
        public static int IndexOf(byte[] srcBytes, byte[] searchBytes, int offset = 0)
        {
            if (offset == -1) { return -1; }
            if (srcBytes == null) { return -1; }
            if (searchBytes == null) { return -1; }
            if (srcBytes.Length == 0) { return -1; }
            if (searchBytes.Length == 0) { return -1; }
            if (srcBytes.Length < searchBytes.Length) { return -1; }
            for (var i = offset; i < srcBytes.Length - searchBytes.Length; i++)
            {
                if (srcBytes[i] != searchBytes[0]) continue;
                if (searchBytes.Length == 1) { return i; }
                var flag = true;
                for (var j = 1; j < searchBytes.Length; j++)
                {
                    if (srcBytes[i + j] != searchBytes[j])
                    {
                        flag = false;
                        break;
                    }
                }
                if (flag) { return i; }
            }
            return -1;
        }
    }
}
